<script lang="ts" setup>
/**
 * 水球图
 */
import * as echarts from 'echarts';
import 'echarts-liquidfill';
import { onBeforeUnmount, onMounted, useTemplateRef } from 'vue';

let chart: echarts.ECharts;
const boxRef = useTemplateRef<HTMLElement>('boxRef');

/**
 * 创建一个矩形画布，背景为上下线性渐变
 */
const createLinearGradientRect = (option: {
    width: number;
    height: number;
    y: number;
    bgColor: HTMLCanvasElement;
    startColor: string;
    endColor: string;
}) => {
    const { width, height, y, bgColor, startColor, endColor } = option;

    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d')!;

    // 绘制背景
    ctx.drawImage(bgColor, 0, 0);

    // 创建线性渐变
    const gradient = ctx.createLinearGradient(0, 0, 0, height);
    gradient.addColorStop(0, startColor);
    gradient.addColorStop(1, endColor);

    // 填充整个矩形
    ctx.fillStyle = gradient;
    ctx.fillRect(0, y, width, height);
    return canvas;
};

let bgCanvas: HTMLCanvasElement | null;

onMounted(() => {
    initChart();

    updateChart(57);
});

onBeforeUnmount(() => {
    chart?.dispose();
    bgCanvas?.remove();
});

const initChart = () => {
    chart?.dispose();
    chart = echarts.init(boxRef.value!, null, {
        renderer: 'svg',
    });
};
const updateChart = (value: number) => {
    // 清除之前的画布，内存回收
    bgCanvas?.remove();
    const limit = 80;
    const radius = (chart.getHeight() / 2) * 0.8;
    // —————————————————————————— 画整个圆环的背景色 ——————————————————————————————————
    bgCanvas = document.createElement('canvas');
    bgCanvas.width = radius * 2;
    bgCanvas.height = radius * 2;
    const ctx = bgCanvas.getContext('2d')!;
    const gradient = ctx.createRadialGradient(
        bgCanvas.width * 0.5,
        bgCanvas.height * 0.5,
        0,
        bgCanvas.width * 0.5,
        bgCanvas.height * 0.5,
        radius,
    );
    gradient.addColorStop(
        0,
        value < limit ? 'rgba(180,210,255,0.93)' : '#ffffff',
    );
    gradient.addColorStop(1, value < limit ? 'rgb(231,241,255)' : '#ffeded');
    ctx.fillStyle = gradient;

    ctx.beginPath();
    ctx.arc(radius, radius, radius, 0, Math.PI * 2);
    ctx.fill();

    // —————————————————————————————————————————————————————————————————————————————
    const option = {
        title: {
            text: 'CPU使用率',
            left: 'left',
        },
        series: [
            // 水球图
            {
                type: 'liquidFill',
                name: '正常',
                // 这个更像是直径
                radius: radius * 2,
                data: [
                    {
                        value: value / 100,
                    },
                ],
                label: {
                    formatter: `${value}%`,
                    // 字体大小，自己调
                    fontSize: 30,
                    color: '#555',
                    fontWeight: 'bold',
                    // 水上部分颜色（可选）
                    insideColor: value < limit ? '#d7e7ff' : '#ff4f4f',
                },
                itemStyle: {
                    // 水的颜色
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                        {
                            offset: 0,
                            color: value < limit ? '#8dbaff' : '#ffcdcd',
                        },
                        {
                            offset: 1,
                            color: value < limit ? '#026eff' : '#ff6363',
                        },
                    ]),
                    // 水的阴影
                    shadowBlur: 1,
                },
                backgroundStyle: {
                    color: new echarts.graphic.RadialGradient(
                        0.5,
                        0.5,
                        radius / 100,
                        [
                            {
                                offset: 0,
                                color: '#ffffff',
                            },
                            {
                                offset: 1,
                                color: value < limit ? '#d7e7ff' : '#ffe2e2',
                            },
                        ],
                    ),
                    // 阴影
                    shadowColor: value < limit ? 'rgb(153,190,246)' : '#ffdbdb',
                    shadowBlur: 100,
                    shadowOffsetY: 10,
                },
                outline: {
                    show: false,
                },
                amplitude: 5, // 振幅
                waveAnimation: true,
                z: 1,
            },
            // 圆环
            {
                type: 'gauge',
                startAngle: 0,
                endAngle: 360,
                radius,
                // 刻度间隔
                pointer: {
                    show: false,
                },
                animation: false,
                progress: {
                    show: true,
                    width: 15,
                    itemStyle: {
                        // 条纹渐变 → 虚线效果
                        color: {
                            image: createLinearGradientRect({
                                width: radius * 2,
                                height: radius * 2,
                                bgColor: bgCanvas,

                                // 下半圆环的裁剪位置
                                y: radius * 2 * (1 - value / 100),

                                // 下半圆环的颜色
                                startColor:
                                    value < limit
                                        ? 'rgb(255,255,255)'
                                        : 'rgb(255,214,214)',
                                endColor:
                                    value < limit
                                        ? 'rgb(0,100,255)'
                                        : 'rgb(255,103,103)',
                            }), // HTMLCanvasElement
                            repeat: 'no-repeat',
                        },
                    },
                },
                axisLine: {
                    show: false,
                },
                // 大刻度
                splitLine: {
                    show: false,
                },
                // 小刻度
                axisTick: {
                    show: false,
                },
                axisLabel: {
                    show: false,
                },
                data: [
                    {
                        value: 100,
                    },
                ],
                detail: {
                    show: false,
                },
                z: 2,
            },
        ],
    };
    chart.setOption(option);
};
</script>

<template>
    <div ref="boxRef" class="c1"></div>
</template>

<style scoped lang="scss">
.c1 {
    height: 300px;
}
</style>
